# OpenGL viewer	by Kristoffer Josefsson

from OpenGL.GL import *
from OpenGL.GLUT import	*
from OpenGL.GLU	import *

from polygon import *
from polyode import *
from texturegl import *

import sys
import time

def	launchConsole(loc=globals()):
	from threading import Thread
	from code import interact
	Thread(target=interact,args=(None,None,loc)).start()

class Scene:
	def	__init__(self):
		self.ESCAPE	= '\033'
		self.window	= 0
		self.rtri =	0.5
		self.t0	= 0.0
		self.t1 = 0.0
		self.triRate = 15.0
		self.rt	= 0.02

		self.bpm = 130

	# from peters lightsetup
	def	initLighting(self):
		glShadeModel(GL_SMOOTH)

		position=[
			[ 1.0, 0.0,	0.0, 0.0],
			[ 1.0, 1.0,	0.0, 0.0],
			[ 0.0, 1.0,	0.0, 0.0],
			[ 0.0, 0.0,	1.0, 0.0]
		]
		diffuse=[
			[ 0.0,	0.4,  0.6, 1.0],
			[ 0.0,	0.6,  0.4, 1.0],
			[ 0.4,	0.6,  0.0, 1.0],
			[ 0.6,	0.4,  0.0, 1.0]
		]
		specular=[
			[ 0.9,	0.0,  0.4, 1.0],
			[ 0.4,	0.7,  0.0, 1.0],
			[ 0.0,	0.7,  0.4, 1.0],
			[ 0.4,	0.0,  0.9, 1.0]
		]
		ambient=[0.07, 0.07, 0.07, 1.0]

		for	i in range(4):
			glLightfv(GL_LIGHT0+i, GL_POSITION,	position[i])
			glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse[i])
			glLightfv(GL_LIGHT0+i, GL_SPECULAR,	specular[i])
			glLightfv(GL_LIGHT0+i, GL_AMBIENT, ambient)
			glEnable(GL_LIGHT0+i)

		glEnable(GL_LIGHTING)

	def	init(self, width, height):
		glClearColor(0.,0.,0.,0.0)	# clear	background color to this
		glClearDepth(1.0)					# enables clearing of depth	buffer
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
		glDepthFunc(GL_LESS)				# type of depth	test to	do
		glEnable(GL_DEPTH_TEST)				# enables depth	testing
		glShadeModel(GL_SMOOTH)				# enables smooth color shading

		glEnable(GL_BLEND)
		glBlendFunc(GL_SRC_ALPHA,	GL_ONE_MINUS_SRC_ALPHA)
	#	glBlendFunc(GL_ONE, GL_DST_ALPHA)
		glEnable(GL_LINE_SMOOTH)
		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
		glEnable(GL_POLYGON_SMOOTH)
		glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)

		self.initLighting()

		import random
	#	self.bill = CelluBill(random.randint(1,255))
		self.bill = ImageBillboard("jojo.png")

		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()					# reset	the	projection matrix
		gluPerspective(45.0, float(width)/float(height), 0.1, 100.0)
						# calculate	aspect ratio of	window
		glMatrixMode(GL_MODELVIEW)

	def	resize(self, width,	height):
		if height == 0:	return
		glViewport(0, 0, width,	height)
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()
		gluPerspective(45.0, float(width)/float(height), 0.1, 100.0)
		glMatrixMode(GL_MODELVIEW)
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

	def	getcoord(self,x,y,z):
		viewport = []
		modelview =	[]
		projection = []
		
		viewport = glGetIntegerv(GL_VIEWPORT)
		#viewport = [0,0,640,480]
		modelview = glGetDoublev(GL_MODELVIEW_MATRIX)
		projection = glGetDoublev(GL_PROJECTION_MATRIX)
		
		nx = ny	= nz = 0
		nx,ny,nz = gluUnProject(x, y, z, modelview, projection, viewport);
		
		return vector([nx,ny,nz])
		

	def	display(self):
		# clear	screen and depth buffer
		glClear(GL_COLOR_BUFFER_BIT	| GL_DEPTH_BUFFER_BIT)
		glClear(GL_DEPTH_BUFFER_BIT)
		glLoadIdentity()				   # reset view
		glTranslatef(0,0.0,-13.0)		 # move	left and into screen
		glRotatef(self.rtri,0.0,1.0,0.2)   # rotate	pyramid	about its y-axis


		glScalef(1+sin(self.t1*2)/2,1+sin(self.t1*4)/2,1+sin(self.t1*8)/2);


	#	self.object.drawCool()
		self.object.draw()
	#	self.object.drawBand()

		self.bill.draw()

		glutSwapBuffers()

	def	idle(self):
		self.t1=time.clock()
		dt=self.t1-self.t0
		if dt>0:
			self.t0=self.t1
			self.rtri += self.triRate*dt
			self.object.compute(time.clock())
			glutPostRedisplay()


	def	keyboard(self, key,	x, y):
		if key == self.ESCAPE:
			sys.exit()
		if key == '1':
			self.object	= polyGL()
			self.object.compute(1)
		if key == '2':
			self.object	= polyGL("p2.data")
		if key == '0':
			self.object	= polyGL("p0.data")
		if key == '3':
			self.object	= polyGL("p3.data")
		if key == '4':
			self.object 	= polyODE()
			self.object.compute(time.clock())
		if key == 'h':
			self.object.holComp	= False
		if key == 'H':
			self.object.holComp	= True

		#print self.object			 

	def	mouse(self,	button,	state, x, y):
		if state ==	0:
			v =	self.getcoord(x,y,0)
			print v
			self.object.append(v)
			self.object.prepare()

		print button, state, x,	y

	def	main(self, argv):
		glutInit(argv)
		glutInitDisplayMode(GLUT_RGBA |	GLUT_DOUBLE	| GLUT_DEPTH)
		glutInitWindowSize(640,	480)
		self.window	= glutCreateWindow("Holonomy")
		#glutFullScreen()

		glutDisplayFunc(self.display)
		glutIdleFunc(self.idle)
		glutReshapeFunc(self.resize)
		glutKeyboardFunc(self.keyboard)
		glutMouseFunc(self.mouse)
		self.init(640, 480)
		self.t0=time.clock()
		self.object = polyODE()
		self.object.compute(self.t0)
		glutMainLoop()


if __name__=="__main__":
	s=Scene()
	launchConsole()
	s.main(sys.argv)
	
